ZONE
Esse sono spazi chiusi da poligoni oppure da sheets di tipo Zone Portal ( es. una stanza chiusa senza uscite risulta essere una zona, ma anche una stanza con una apertura chiusa completamente da una sheet Zone Portal invisibile ). Ogni zona pu≥ essere caratterizzata da variazioni nella gravitα, velocitα, dannositα, riverbero, ecc. Tutto ci≥ che Φ peculiare di una zona non risulta visibile da un’altra zona ( un esempio Φ la nebbia ). Ci≥ si riflette anche sulle luci e sulle trasparenze; qualora vogliate creare un poligono masked ( es. una grata di spessore 1 che chiuda un tunnel ), se la create grande uguale all’imboccatura del tunnel genererete due zone distinte, per le quali la luce presente in una non Φ visibile nell’altra: il risultato Φ che non potete vedere attraverso i buchi della grata il tunnel retrostante. Per risolvere il problema basta creare la grata leggermente pi∙ piccola ( 1 di meno in una qualsiasi direzione risulta pressochΦ impercettibile e utile allo scopo ): in questo modo entrambi i lati del tunnel appartengono alla stessa zona.Per fornire un nome ad un settore di un livello
( in modo da ottenere informazioni sulle correnti posizioni dei
propri compagni di squadra ) bisogna dividere il livello in zone
con le solite sheet ed in ogni zona inserire uno ZoneInfo ( se
non Φ giα presente uno ): sotto ZoneInfo>LocationStrings
scegliere il nome che verrα visualizzato ( tipo Base Rossa
oppure Corridoio Centrale ) durante il gioco.
![]() ( esempio di divisione per zone in visuale Zone/Portal view: la zona in verde chiaro Φ acqua divisa da una sheet ( Zone portal ); analogamente per la lava in azzurro nonchΦ per i due settori in rosso e blu, che sono divisi da una sheet all'imboccatura del tunnel. Invece la sezione in verde Φ chiusa e fa zona a sΦ ) |
Altre
opzioni importanti disponibili sotto ZoneInfo>ZoneInfo: bBounceVelocity = gli oggetti rimbalzano in caduta se Φ una velocity zone bDestructive = elimina i frammenti di cadavere bFogZone = abilita l'uso della nebbia bGravityZone = abilita variazioni della gravitα bKillZone = uccide chiunque entri nella zona bMoveProjectiles = consente il movimento dei proiettili bNeutralZone = nessuno pu≥ essere ferito nella zona bNoDecals = non vengono visualizzati sangue ed esplosioni sulle pareti bNoInventory = gli oggetti rilasciati dai giocatori scompaiono bPainZone = abilita l'uso del dolore bWaterZone = consente l'effetto liquido nella zona DamagePerSec = velocitα del dolore inferto ( il bPainZone viene abilitato in automatico ) DamageString = messaggio che compare alla morte in quella zona ( deve essere DamageType=SpecialDamage ), dove %k Φ il parametro che visualizza il nome dell'uccisore e %o quello del malcapitato DamageType = definisce il tipo di dolore ( burned, airborne, drowned, corroded, hacked, fell, exploded, special ), con conseguente tipo di suoni e morte EntryActor = effetto visivo all'ingresso nella zona ( deve essere bWaterZone=True, come nelle seguenti 3 opzioni ) EntrySound = effetto sonoro all'ingresso nella zona ExitActor = effetto visivo all'uscita dalla zona ExitSound = effetto sonoro all'uscita dalla zona MaxCarcasses = massimo di carcasse contemporanee ZoneFluidFriction = resistenza del liquido al movimento del Pawn ( viscositα ) ZoneGravity = definisce il vettore della gravitα, normalmente verticale ZoneGroundFriction = resistenza del pavimento al movimento del Pawn ( scivolositα ) ZonePlayerEvent = attiva un evento appena il giocatore entra nella zona ZoneTag = consente l'attivazione da parte di un Triggers\Trigger\ZoneTrigger ( che dovrα avere uguale Event ), il quale effettuerα lo switch del bPainZone in automatico ZoneVelocity = velocitα fissa all'interno della zona Bisogna sottolineare come giα la scelta di un certo tipo di zona sotto Info\ZoneInfo risparmi la maggior parte delle precedenti impostazioni e soprattutto renda inutile la modifica dei parametri di ZoneInfo>ZoneLight. |
Applicare texture: le texture vanno caricate con Load ( sono a pacchetti di immagini PCX/BMP a 8 bit ) in basso a destra in quanto all’avvio del programma vi sono solo quelle di base, mentre ad ogni caricamento di un livello verranno aggiunte anche le texture utilizzate in quest’ultimo. Per applicarle cliccare sulla faccia di un poligono ( diventerα a griglia blu ) e poi sulla texture desiderata. Per creare un poligono con una certa texture, selezionarla e poi aggiungere o sottrarre il brush. Ricordo che quando si fa Intersezione/Deintersezione selezionare prima la texture desiderata, in quando poi aggiungendo o sottraendo il brush risultante non potrete sceglierla pi∙. Per velocizzare le modifiche di pi∙ texture fare clic dx su una texture e in Select utilizzare la funzione pi∙ consona. In Align Selected invece si possono allineare texture uguali adiacenti per evitare che si veda che appartengono a poligoni diversi, mentre con Reset si annullano tutte le variazioni dell’allineamento della texture.
Per la selezione delle texture, un brush modello opera in due modalitα: nella prima, quando lo si seleziona dalle icone, aggiungendolo o sottraendolo si utilizza la texture attualmente selezionata; nella seconda, se si ha utilizzato Copy Poligons -> To Brush, si ha importato, oppure se si ha intersecato ( e poi aggiunto a parte ) un oggetto, il modello utilizza le texture dell’oggetto sorgente, non quella definita dall’utente.
Per le superfici dei pannelli/schermi, specialmente se trasparenti, conviene nelle proprietα delle superfici selezionare Unlit ( le luci non hanno effetto sulla superficie ) e Special Lit ( la superficie ha una illuminazione speciale che non ha effetto sugli oggetti circostanti ).
Per lo screenshot descrittivo del livello bisogna importare un'immagine 256x256 di nome screenshot ( formato PCX o BMP ) nel pacchetto MyLevel: poi si va sotto Options|Level properties e sotto LevelInfo\Screenshot applicare l'immagine interessata. Il pacchetto MyLevel non va salvato, in quanto le texture vengono integrate nel file di livello.
Creare texture: per crearla si utilizza un qualsiasi programma di fotoritocco e si salva l’immagine in formato PCX a 8 bit con le dimensioni in multipli di 16 pixel. Poi in UnrealEd si esegue Import fra le opzioni delle texture ( scegliendo il pacchetto di destinazione ed eventuale argomento ) e, una volta importata si fa Save. Una opzione importante nelle proprietα delle texture ( accessibili tramite l’opzione Edit ) si trova in Texture\DetailTexture, che imposta la maschera di definizione quando ci si avvicina molto ad una texture: nel pacchetto Detail si trova per esempio la texture Scanline, che introdotta in DetailTexture dα l’effetto interlacciato ad una texture ( es. i pannelli ); non scegliere mai masked se si vuole un effetto di dettaglio, altrimenti quest’ultimo non sarα visibile. Una volta effettuata una modifica ad un pacchetto di texture, ricordarsi di fare prima "Compile Changed Scripts" e poi Save tra le opzioni delle texture.
Per creare texture Scripted bisogna procedere in modo particolare: anzitutto le texture Scripted consentono di variare durante il gioco la texture posta sulla loro superficie oppure di effettuare altre azioni come scorrimento testo. La loro creazione parte dalla barra Browse: scegliere Textures e poi fare New; sotto Class scegliere ScriptedTexture e definire le dimensioni, nonchΦ il nome che dovrα avere la texture. Ora si deve fare clic dx sulla texture e sceglierne le proprietα: sotto ScriptedTexture c'Φ SourceTexture, in cui va selezionata la texture che darα l'aspetto alla ScriptedTexture.
Animare texture: create tutti i frame dell’animazione in formato PCX 8 bit e dategli nome Nome_A##.pcx, in cui ## Φ il numero del frame ( il primo Φ 00 ) e Nome Φ un nome a scelta. Facendo cos∞ UnrealEd riconosce che le texture sono frame di una animazione ed imposta automaticamente la sequenza secondo la numerazione. Importate tutti i frame e ricompilate gli script; infine salvate il pacchetto di texture. Per applicare la texture animata, scegliere un frame qualsiasi ed applicare. Nelle proprietα di ciascuna texture, sotto Animation, vi Φ il range di framerate da rispettare. Se volete una animazione pi∙ lenta, bisogna ridurre MaxFrameRate. Teoricamente i settaggi per il framerate andrebbero impostati per ogni singolo frame, per≥ Φ sufficiente farlo per uno solo, ossia quello che imposterete come primo nell’animazione.
ScrollingMessageTexture:
visualizza
messaggi fissi o variabili tramite ScriptedTexture. Si introduce in un punto qualunque del
livello un Info\ClientScriptedTexture\ScrollingMessageTexture e
si va ad editare anzitutto
ScrollingMessageTexture>ClientScriptedTexture, scegliendo la
texture Scripted di destinazione del messaggio: a causa della genericitα
dell'oggetto, tutte le texture dello stesso nome/pacchetto
visualizzeranno quel messaggio ( per evitare il problema bisogna attribuire
diversi nomi a texture uguali ).
Le opzioni di visualizzazione risiedono sotto ScrollingMessageTexture>ScrollingMessageTexture:
bCaps
= vero per bloccare le lettere in
maiuscolo
bResetPosOnTextChange
= quando il testo cambia causa
script, l'area si azzera e il nuovo testo appare all'inizio
PixelsPerSecond
= velocitα di movimento, da destra verso
sinistra
ScrollingMessage
= il messaggio interessato;
parametri: %lp, %lf, %p, rispettivamente miglior fragger, miglior
punteggio, nome giocatore locale
ScrollWidth =
ampiezza di
visualizzazione del testo prima che scompaia
YPos
= decentramento verticale del testo
SKIN: per creare o modificare le skin dei giocatori il procedimento Φ manuale. Le skins si trovano in vari pacchetti sulla base del sesso e della categoria ( CommandoSkins, SoldierSkins, FCommandoSkins, SGirlSkins ): prenderemo come esempio il pacchetto SoldierSkins.utx. Ad ogni pacchetto Φ associato un file di testo che invece configura l'uso di queste texture: nel nostro caso SoldierSkins.int , all'interno della cartella /System del gioco; poniamo prima che vogliamo creare una nuova squadra di nome Temp e con due rappresentanti, John e Bob: dobbiamo aprire SoldierSkins.int con un editor di testo ed aggiungere le seguenti linee:
Object=(Name=SoldierSkins.prova1,Class=Texture,Description="Temp")
Object=(Name=SoldierSkins.prova2,Class=Texture)
Object=(Name=SoldierSkins.prova3,Class=Texture)
Object=(Name=SoldierSkins.prova4,Class=Texture)
Object=(Name=SoldierSkins.prova4John,Class=Texture,Description="John")
Object=(Name=SoldierSkins.prova4Bob,Class=Texture,Description="Bob")
Object=(Name=SoldierSkins.prova5John,Class=Texture)
Object=(Name=SoldierSkins.prova5Bob,Class=Texture)
Object=(Name=SoldierSkins.prova1T_0,Class=Texture)
Object=(Name=SoldierSkins.prova1T_1,Class=Texture)
Object=(Name=SoldierSkins.prova1T_2,Class=Texture)
Object=(Name=SoldierSkins.prova1T_3,Class=Texture)
Object=(Name=SoldierSkins.prova2T_0,Class=Texture)
Object=(Name=SoldierSkins.prova2T_1,Class=Texture)
Object=(Name=SoldierSkins.prova2T_2,Class=Texture)
Object=(Name=SoldierSkins.prova2T_3,Class=Texture)
Descrizione linee:
01: prova Φ il nome dei file della squadra
( quindi tutti i file della squadra dovranno iniziare con prova ), che ha nome
Temp.
Questo primo file contiene il petto, il dorso e i bracciali delle texture
standard
02: contiene gambe e piedi standard
03: contiene spalle e braccia restanti ( invariante
per colore Team )
04: contiene testa e mani di default ( invariante
per colore Team )
05: contiene testa e mani di un giocatore che ha
nome John
06: contiene testa e mani di un giocatore che ha
nome Bob
07: portrait di John
08: portrait di Bob
09: variante di prova1 per Team 0 ( Rosso )
10: variante di prova1 per Team 1 ( Blu )
11: variante di prova1 per Team 2 ( Verde )
12: variante di prova1 per Team 3 ( Oro )
13: variante di prova2 per Team 0 ( Rosso )
14: variante di prova2 per Team 1 ( Blu )
15: variante di prova2 per Team 2 ( Verde )
16: variante di prova2 per Team 3 ( Oro )
I nomi di file utilizzati ( prova2T_1, prova4John, ecc. ) vanno rispettati
nell'introduzione delle texture. Tutte le texture vanno create in formato PCX
256x256 a 8 bit, esclusi i portrait che sono in 64x64; una volta create con un
programma di fotoritocco adeguato, vanno importate con la funzione Import nella
barra Browse,Texture. Creare i file PCX giα col nome da utilizzare nel
pacchetto utx, di modo che la funzione Import suggerisca giα il nome corretto
da utilizzare; il pacchetto di destinazione naturalmente Φ SoldierSkins. Una
volta importate tutte le skin dichiarate in SoldierSkins.int, si pu≥ salvare il
pacchetto tramite l'opzione Save.
Nel caso in cui invece si voglia solamente modificare una texture giα presente
bisogna prima fare Export ( preferibilmente con lo stesso nome ) e
modificarla mantenendo il formato grafico, dopodichΦ fare Import del file PCX
modificato e Save del pacchetto. In questo caso chiaramente non ci sono
cambiamenti da fare in SoldierSkins.int.
Luci:
si
introducono con una Light semplice ( basta fare clic dx su una
superficie e selezionare Add Light here ), la quale ha giα una
luminositα predefinita: per vederne l’effetto fare Lighting
Rebuilt.
Opzioni importanti per una Light:
( sotto Light>LightColor
)
LightBrightness = luminositα della luce
LightHue = tono della luce
LightSaturation = saturazione della luce
( sotto Light>Lighting
)
bCorona = abilita l'effetto corona
bSpecialLit = l'illuminazione esterna non ha
effetto ( nel caso di una Light, essa non genera
luce ma pu≥ generare nebbia per esempio )
LightCone = ampiezza del cono di luce
LightEffect = effetto della luce
LightPeriod = durata del ciclo dell'effetto
LightPhase = sfasatura del ciclo ( utile con pi∙
luci )
LightRadius = estensione della luce
LightType = tipo di luce
VolumeBrightness = luminositα della nebbia
VolumeFog = densitα della nebbia
VolumeRadius = estensione della nebbia associata
alla luce
Bisogna precisare che qualsiasi oggetto pu≥ creare luce, basta solo impostare il LightColor, il Lighting\LightRadius e Lighting\LightType, cosa giα presente nella canonica Light. Per generare luce diffusa a tutta la zona ( quindi per≥ senza ombre ) si pu≥ introdurre un Info\ZoneInfo e impostare le proprietα in ZoneLight. Per generare luce condensata in un’area si pu≥ utilizzare Light>Lighting\LightEffect=LE_Cylinder e un LightRadius molto ridotto.
Per implementare certi effetti di luce ( quelli di LightType principalmente ) su singole superfici, per esempio per visualizzare una barra che pulsa, bisogna utilizzare una luce con ( nel caso della pulsazione ) Lighting\LightType=LT_Pulse e Lighting\bSpecialLit=True e analogamente Special Lit nelle proprietα della superficie interessata: il risultato Φ che quella luce avrα effetto unicamente sulle superfici di tipo Special Lit. In questo modo si possono applicare effetti di luce localizzati senza influire sull'ambiente circostante.
Una piccola nota riguardo all’effetto corona. Per utilizzarlo fate Light>Lighting\bCorona=True, applicate in Display\Skin una texture adatta ( es. SpaceFX,3e ) e riducete adeguatamente le dimensioni della luce in Display\DrawScale ( 0.3 dovrebbe andare bene). L’effetto non Φ visibile qualora il pivot della luce non sia immediatamente visibile ( ci≥ vale anche se si trova oltre un poligono trasparente o invisibile, basta che sia solido, quindi oltre una sheet Φ visibile ) nonchΘ quando ci si trova oltre il LightRadius.
Fiamme: utilizzate una sheet con orientamento verticale di dimensioni pari alla texture da usare. Scegliete una texture del fuoco ( per esempio il pacchetto GreatFire, AncFlame1 ) e fate Add Special. Scegliete Masked e 2 Sided e applicate. Effettuate le dovute correzioni e poi ruotate la sheet di 45░ e fate nuovamente Add Special. Ripetete la procedura fino ad ottenere la fiamma ad otto raggi ( o pi∙, per renderla ancora pi∙ realistica ). Aggiungete a questo punto una luce nel centro e nella sue proprietα Lighting\Lighteffect scegliete l’effetto adatto (LE_TorchWaver) . Correggete luminositα e colore e siete a posto. Sotto la fiamma volendo potete mettere come supporto un cubo adeguatamente texturizzato oppure usate l’oggetto Decoration\Urn e rendetelo indistruttibile ( Collision\bCollideActors=False ). Si pu≥ poi aggiungere un suono attraverso un Triggers\SpecialEvent. Si pu≥ anche creare fiamme che sembrano fuoriuscire dalla lava ( Φ meglio usare come texture NaliFX,TORCHES3 ), utilizzando un Mover: si imposta il primo keyframe sotto la lava e il secondo parzialmente fuori, ed un MoveTime di circa 3 secondi. Poi si attivano queste fiamme attraverso uno StochasticTrigger, che le genera casualmente per rendere il tutto pi∙ realistico.
Acqua e lava sono zone: anzitutto dovete creare un buco nel pavimento, ove risiederα il bacino acqueo o magmatico ( un cubo di 200*200*200 per esempio ). Poi dovete creare la superficie di delimitazione della zona attraverso una sheet orizzontale delle stesse dimensioni della pozza ( 200*200 nel nostro caso ). E’ importante perchΘ deve fisicamente dividere l’interno della pozza ( dove si troverα acqua o lava ) dalla zona esterna dove ci troviamo: di conseguenza dobbiamo anche mettere la sheet un poco pi∙ sotto del livello del pavimento altrimenti sembrerα che il liquido debba traboccare. Facciamo quindi Add Special per tale sheet utilizzando la texture adatta ( in Liquids per le acque e in FireEng per le lave ), applichiamo scegliendo le impostazioni water per l’acqua e water senza trasparenza per la lava.
Adesso dobbiamo rendere d’acqua o lava l’interno della pozza: mettiamo all’interno quindi un Info\ZoneInfo\WaterZone o Info\ZoneInfo\LavaZone a seconda del tipo scelto e siamo a posto. Se vogliamo possiamo nel caso dell’acqua inserire una musica d’atmosfera operando sulle WaterZone>Sound\AmbientSound applicando per esempio il SoundFX Amboutside\swmp7. Per la lava poi naturalmente si pu≥ scegliere la velocitα di morte con LavaZone>ZoneInfo\DamagePerSec.
Si consiglia per l’acqua di applicarvi luci con Lighting\LightEffect=LE_WateryShimmer mentre per il fuoco luci con Lighting\LightEffect=LE_FireWaver, preferibilmente rosso tenue.
Il cielo si compone di due elementi: una o pi∙ superfici che visualizzeranno il cielo ed uno skybox, ossia la "scatola" contenente l’aspetto del cielo.
Lo skybox si crea sottraendo un parallelepipedo di altezza 250 e base 2500*2500 in una parte totalmente esterna al proprio livello. Lo si texturizza per esempio con Genfluid,Skytst7 e gli si dα V-Pan o U-Pan ( il movimento E-O o N-S ). Poi si crea a metα altezza una sheet trasparente ( sul piano orizzontale e sempre 2500*2500 ) utilizzando come texture Genfluid,Skytst9 e dandogli lo stesso movimento dell’altro soffitto. Questo dα l’effetto di un cielo multistrato: volendo si pu≥ aggiungere sheets su sheets per renderlo ancora pi∙ realistico, anche se due strati sono pi∙ che sufficienti. Fatto ci≥ si inserisce un Info\ZoneInfo\SkyZoneInfo e lo si mette al centro del parallelepipedo. Questo punto Φ la locazione da dove si vedrα il cielo nel proprio livello. Per vedere il cielo bisogna per≥ ancora aggiungere nelle proprietα della superficie del "soffitto" del proprio livello l’opzione Fake Backdrop ( presente in Effects ) che fa in modo tale da vedere invece della texture il cielo.
Ora se si vuole si possono aggiungere le montagne in sottofondo: alla base della scatola del cielo in posizione centrale si incava un altro parallelepipedo che deve fuoriuscire sotto quello precedente di circa 150, mentre la base Φ di 500*500; bisogna poi inserire delle sheets ( ad orientamento verticale e altezza doppia del parallelepipedo piccolo ) sulle facce del parallelepipedo piccolo: ad esse applichiamo ( masked ) con Add Special una texture del pacchetto SkyBox, scalandola opportunamente ( 2X verticalmente ). Infine ci vogliono le luci, da mettere sopra lo strato pi∙ basso e diffusamente su tutta la superficie dello strato ( meglio se senza alcun effetto e con Lighting\LightRadius molto grande ). Lo SkyZoneInfo in questo caso va posizionato pi∙ in basso, dentro la scatola pi∙ piccola.
Per creare un sole utilizzare pi∙ luci nello stesso punto, magari con effetto corona. Si consiglia poi di creare nel livello pareti alte oppure montagne per evitare di vedere gli altri lati della scatola del cielo.
![]() ( la parte interna dello skybox: si nota al centro lo SkyZoneInfo e attorno le sheet delle montagne. In alto sono presenti due sheet di un sole, adeguatamente illuminate ) |
![]() ( lo skybox da lontano: notare la sheet delle nuvole a mezza altezza nonchΦ il fatto che la parte interna dello skybox sia ribassata rispetto al resto ) |
La nebbia innanzitutto necessita di un Info\ZoneInfo nella zona in cui si vuole posizionarla: poi devÆessere ZoneInfo>ZoneInfo\bFogZone=True. Qualora ci sia giα un ZoneInfo di genere specifico ( LavaZone,ecc. ) basta applicare l’opzione nebbia a quest’ultimo. La nebbia per≥ viene generata dalle luci: applichiamo il volume della nebbia alle luci che ci interessano agendo su Light>Lighting\VolumeRadius ( giα valori come 13 offrono molta ampiezza ). Per vedere la nebbia da un’altra zona bisogna che anche in quest’ultima sia bFogZone=True.
Nebbia mobile: in una zona con nebbia attivata si crea un piccolo Mover invisibile ( Add Special, Invisible e Non-Solid ) e gli si dα i parametri corretti per una luce, introducendo LightType ( LT_Steady normalmente, ma si pu≥ utilizzare qualsiasi tipo ), LightRadius, VolumeBrightness e VolumeRadius ( piccolo ), nonchΘ ovviamente i valori del LightColor. Poi si scelgono i Keyframe e l’attivazione. Ricordare che il centro della nebbia Φ il pivot del Mover.
Portale: per crearlo bisogna innanzitutto avere a disposizione un poligono come pu≥ essere un corridoio. Il buco naturalmente deve essere tale da poterci entrare. A questo punto si chiude il buco da tutti e due i lati (o uno solo, se il buco non porta da alcuna parte ) con delle sheets non solide di dimensioni pari al buco. La cosa migliore Φ comunque incavare un parallelepipedo su una facciata di un muro, coprire quest’unico lato con la sheet e proseguire. La sheet se si vuole si pu≥ farla trasparente per vedere effettivamente la destinazione del portale, l’importante Φ che sia Zone Portal. Per attivare il portale bisogna inserire all’interno del buco ( fra sheet e muro ) un Info\ZoneInfo\WarpZoneInfo e in WarpZoneInfo>WarpZoneInfo\OtherSideURL=Portal2 ( nome a scelta ) e ThisTag=Portal1 ( sempre a scelta ). Nel secondo portale bisogna solamente invertire l’OtherSideURL e il ThisTag affinchΦ uno porti nell’altro e viceversa. Poi con svariati portali si possono creare diverse combinazioni. E’ importante, affinchΦ non ci siano problemi di clipping, che i portali abbiano la facciata delle stesse dimensioni, soprattutto se si vuole vedere la destinazione del portale. Inoltre la direzione d’entrata di uno deve essere uguale alla direzione d’uscita dell’altro.
Teleporter: ( NavigationPoint\Teleporter ) essi trasportano quando
si tocca un’area di raggio a scelta, non quindi una zona. Il
Teleporter di partenza va settato con corretti
Collision\CollisionRadius e Collision\CollisionHeight per
decidere lo spazio di teletrasporto, poi in Teleporter>Teleporter
vi sono le opzioni:
bChangesVelocity
= l'uscita del Teleporter avviene ad una velocitα
data dal TargetVelocity
bChangesYaw = se si
voglia che all’arrivo il personaggio sia rivolto nella
direzione della freccia del Teleporter di arrivo
bEnabled = se Φ inizialmente attivo ( lo switch
viene effettuato da un Trigger )
bReverseX = la velocitα in arrivo nell'asse X
viene invertita
bReverseY = la velocitα in arrivo nell'asse Y
viene invertita
bReverseZ = la velocitα in arrivo nell'asse Z
viene invertita
TargetVelocity = velocitα imposta in uscita
URL = il Tag del Teleporter di
arrivo
I Trigger normali (Triggers\Trigger) sono fondamentali e eseguono l'oggetto dichiarato in Trigger>Events\Event. In pratica l’Event di un Trigger deve corrispondere al Events\Tag dell’oggetto che si vuole attivare: una volta effettuata questa corrispondenza nelle visuali in wireframe Φ presente una linea rossa che collega il Trigger con i suoi eventi ( Φ possibile che un Trigger generi pi∙ eventi, basta che questi abbiamo appunto tutti lo stesso Tag e questo appunto sia uguale all'Event del Trigger). Tutti gli oggetti in Triggers sono Trigger; altri Trigger possono essere i Mover quando vengono attivati: in seguito si parlerα di oggetti attivati via Trigger, sottintendendo che anche Mover o altri oggetti possono fare altrettanto. Un Trigger di default esegue l’attivazione quando un personaggio si avvicina a lui: la zona di attivazione del Trigger Φ valida in uno spazio cilindrico dato da un raggio ed una altezza dal Trigger che sono impostabili in Trigger>Collision. Per visualizzare precisamente il radius di un Trigger o anche di un altro oggetto, si pu≥ scegliere nelle opzioni del quadrante planare XY l’opzione Actors|Radii View, che mostra il raggio ( se disponibile ) dell’oggetto selezionato.
Le opzioni disponibili sotto Trigger>Trigger:
bInitiallyActive = se Φ inizialmente attivo
bTriggerOnceOnly = se pu≥ essere attivato una sola
volta
ClassProximityType = tipo di classe che pu≥
attivare il Trigger
DamageThreshold = danno singolo minimo per attivarlo ( il Trigger
deve essere di tipo TT_Shoot ), di modo che solo le
armi pi∙ potenti abbiano effetto
Message = messaggio associato all'attivazione (
visibile nella finestra in alto a sinistra )
ReTriggerDelay = tempo di attesa prima di poter
riattivare il Trigger
TriggerType =
modalitα di attivazione del Trigger:
TT_PlayerProximity = all'avvicinamento del
giocatore
TT_PawnProximity =
all'avvicinamento di qualsiasi Pawn
TT_ClassProximity =
all'avvicinamento di un Actor
specificato sotto Trigger\ClassProximityType
TT_AnyProximity =
qualunque Actor lo
attiva per prossimitα
TT_Shoot = se si vuole
attivarlo colpendolo
Non tutti i tipi di Triggers si attivano a contatto/sparo: alcuni, quali per
esempio gli SpecialEvent
devono essere attivati essi stessi da un Trigger.
Stato iniziale sotto Trigger>Object\InitialState:
NormalTrigger
= stato di normale attivazione
OtherTriggerTurnsOff
= un Trigger
qualunque a lui collegato pu≥ disabilitarlo
OtherTriggerTurnsOn
= un
Trigger
qualunque a lui collegato pu≥ abilitarlo
OtherTriggerToggles
= un
Trigger
qualunque a lui collegato pu≥ alternare l'abilitazione
Per esempio abbiamo un Mover di Tag "Porta" che vogliamo attivare da un Trigger: innanzitutto in Mover>Object\InitialState deve essere TriggerOpenTimed ( = il Trigger controlla il movimento dell’oggetto, che comunque non pu≥ essere riattivato fino a quando non ha completato il movimento ) o analoghi basati sul controllo Trigger. Adesso diamo a Trigger>Events\Event il Tag del Mover ("Porta") e posizioniamo il Trigger a portata d’uomo dove metteremo l’apposito switch.
![]() ( Un esempio di applicazione complessa di Triggers: tre semplici Trigger con attivazione a prossimitα fanno muovere le leve; il movimento di ogni leva incrementa il Counter, che arrivato a 3 attiva il Dispatcher; quest'ultimo, dopo il tempo di attesa previsto, aprirα una porta ) |
Counter: permette di attivare un evento dopo che un certo numero di Trigger sono stati attivati. Per esempio prendiamo quattro Triggers\Trigger che, una volta attivati tutti, facciano aprire una porta. Create il Mover della porta e facciamo che l’attivazione avviene una sola volta, con la porta che resta aperta: facciamo Mover>Object\InitialState=TriggerToggle. Introduciamo un Triggers\Counter e lo mettiamo dove vogliamo. Facciamo Counter>Counter\NumToCount=4 ( il numero dei Trigger ). Poi per ogni Trigger diamo come Event il Tag del Counter e scegliamo Trigger\bTriggerOnceOnly=True. Dispatcher: serve a ritardare un evento. Vogliamo ad esempio che l’interruttore che attiva l’ascensore lo faccia partire dopo un paio di secondi, tempo necessario a raggiungere la piattaforma. A tal fine, dopo aver creato il nostro Mover/ascensore utilizziamo prima un Trigger normale collegato ad uno Triggers\SpecialEvent e al Triggers\Dispatcher ( per fare ci≥ diamo all’Event del Trigger lo stesso Tag di SpecialEvent e Dispatcher, per esempio "Activate1" ): allo SpecialEvent diamo un suono che indica l’attivazione dell’interruttore ( in SpecialEvent>SpecialEvent\Sound, facendo anche SpecialEvent>Object\InitialState=PlaySoundEffect ) mentre il Dispatcher ritarderα l’ascensore ( Dispatcher>Dispatcher\OutEvents\[0]=Elevator (il Tag del Mover ) e Dispatcher>Dispatcher\OutDelays\[0]=2 ( 2 secondi di ritardo )). Ovviamente il Dispatcher pu≥ controllare fino ad otto eventi separati. StochasticTrigger: genera una serie di eventi con una certa probabilitα di riuscita, in maniera tale che sembrino casuali; un esempio possono essere le fiammate della lava, che si vuole fuoriescano in maniera casuale. Si introduce un Triggers\StochasticTrigger e si sceglie in Object\InitialState se AlwaysActive o TriggerActive. Scegliamo il primo e in StochasticTrigger>StochasticTrigger\Events introduciamo il Tag degli oggetti da attivare ( se introduciamo due volte lo stesso Tag, la probabilitα per quell’evento aumenta ). Nelle tre restanti opzioni impostiamo il tempo min/max per riprovare ad attivare l’evento, nonchΘ la probabilitα ( da 0 a 1 ). |
specialevent: il Triggers\SpecialEvent viene attivato
via Trigger ed Φ uno degli oggetti pi∙ versatili
presenti fra i Triggers. Infatti se ne possono fare diversi usi, disponibili
sotto SpecialEvent>Object\InitialState:
PlayerPath
= Φ il generatore di un sentiero per il giocatore (
con Keypoint\InterpolationPoint
)
PlayAmbientSoundEffect
= per eseguire un
suono di tipo Looping dal punto in cui si trova lo SpecialEvent
PlayersPlaySoundEffect
= qualora si voglia che ogni giocatore senta questo suono
PlaySoundEffect
= per eseguire
un
suono di tipo OneShot dal punto in cui si trova lo SpecialEvent
KillInstigator
= l'attivazione uccide il giocatore
DamageInstigator
= l'attivazione causa danno al giocatore ( necessita di
impostare SpecialEvent\Damage
)
DisplayMessage
= visualizza un messaggio nella finestra in alto (
impostare SpecialEvent\Message
);
Le opzioni invece sono in SpecialEvent>SpecialEvent:
bBroadCast
= il messaggio viene mostrato a tutti i giocatori
bPlayerViewRot
= se il giocatore pu≥ ruotare durante il sentiero
Damage = danno inferto
al giocatore
DamageString =
messaggio visualizzato alla morte del giocatore ( necessita di DamageType=SpecialDamage
)
DamageType = tipo di dolore/morte ( burned,
airborne, drowned,
corroded, hacked, fell,
exploded, special )
Message = messaggio (
non necessita specificamente di Object\InitialState=DisplayMessage
)
Sound = suono Looping
o OneShot
MUSICEVENT: il
Triggers\MusicEvent
consente una transizione di musica durante il gioco. Un uso sensato in Unreal
Tournament pu≥ essere nell'Assault, magari quando si passa alla fase pi∙
concitata della difesa. Il MusicEvent
necessita di un Trigger
per funzionare. Le opzioni in MusicEvent>MusicEvent:
bAffectAllPlayers
= ha effetto su tutti i giocatori
bOnceOnly =
attivabile una sola volta
bSilence =
solamente interrompe la musica attuale
CdTrack =
traccia CD da riprodurre ( 255 = nessuna )
Song = musica
da riprodurre
SongSection =
sezione della musica da riprodurre
Transition =
metodo di transizione dalla musica/traccia precedente
distanceviewTrigGER: il Triggers\DistanceViewTrigger, attivato
via Trigger, consente di attivare i Pawn compresi nello spazio definito dal DistanceViewTrigger>Collision\CollisionHeight
e CollisionRadius ( utile per mettere in allerta le
torrette ).
fadeviewtrigger:
il Triggers\FadeViewTrigger genera un
effetto di dissolvenza di luce applicato a tutto il livello ( per esempio pu≥
essere utilizzato per eventi globali come la fine di un livello in Assault ).
Necessita dell'attivazione via Trigger. Le opzioni
sotto FadeViewTrigger>FadeViewTrigger:
bTriggerOnceOnly = pu≥ essere attivato una volta
sola ( in caso contrario, la riattivazione riporta la luce allo stato normale )
FadeSeconds = durata della transizione
TargetFlash = luminositα di arrivo, espressa come
vettore ( necessariamente negativo, ha un valore giα corretto )
TriggerLight: una luce che, controllata da un Trigger normale, pu≥
attivarsi e disattivarsi. Introducete un Light\TriggerLight
e
scegliete in Object\InitialState la funzione del Trigger.
Le opzioni sono in TriggerLight>TriggerLight:
bInitiallyOn = se la luce Φ inizialmente accesa e il
Trigger la spegne o viceversa
bDelayFullOn = se la luce ritarda e poi si accende completamente
ChangeTime = tempo di passaggio da acceso a spento
( cambiamento di luce graduale se bDelayFullOn=False
)
RemainOnTime = quanto tempo rimane accesa la luce nel caso di Object\InitialState=TriggerPound
Un
problema Φ che se la luce usa l’effetto corona,
quest’ultimo resta attivo anche quando spenta.
Kicker:
serve a fornire una spinta al giocatore in qualunque direzione. In
Kicker>Kicker si sceglie:
bKillVelocity = la velocitα di arrivo del
giocatore viene annullata ( altrimenti viene sommata a quella del Kicker
)
bRandomize = l'
intensitα/direzione della spinta Φ casuale ( Φ comunque funzione della KickVelocity
scelta )
KickedClass = normalmente Pawn ( valido quindi per
tutti )
KickVelocity = la velocitα di spinta, intesa in
tutte e tre le dimensioni
TEAMTrigGER: il Triggers\Trigger\teamtrigger serve a far generare un evento solo da parte di un giocatore non appartenente alla squadra selezionabile in teamtrigger\Team.
TIMEDTRIGGER: il Triggers\Trigger\TimedTrigger genera un evento con cadenza fissa selezionabile in TimedTrigger\DelaySeconds; questo Trigger non viene attivato a contatto bens∞ all'avvio del livello e continua a generare l'evento se si ha selezionato TimedTrigger\bRepeating=True.
zonetRIGGER: il Triggers\Trigger\ZoneTrigger effettua lo switch del bPainZone di una zona: per fare ci≥ il ZoneTrigger>Events\Event deve essere uguale al ZoneInfo>ZoneInfo\ZoneTag.
TRIGGEREDDEATH: il Triggers\TriggeredDeath uccide chi
entra nel suo raggio d'azione ed Φ particolarmente utile nel caso di morte per
caduta, infatti Φ possibile impostare una dissolvenza. Le opzioni sotto TriggeredDeath>TriggeredDeath:
bDestroyItems = un eventuale oggetto d'inventario
verrebbe distrutto
ChangeTime = tempo fra l'attivazione e l'effettiva
morte
DeathName = tipo di morte ( fell
di default, altrimenti burned,
airborne, drowned,
corroded, hacked, exploded,
o special )
EndFlashFog = fog finale dove XYZ sta per RGB ( con
valori fra 0 e 1 per tutte e tre le componenti )
EndFlashScale = scalamento del fog finale
FemaleDeathSound = suono di morte per classe
femminile ( comunque configurabile tramite DeathName
)
MaleDeathSound = suono di morte per classe maschile
( comunque configurabile tramite DeathName )
StartFlashScale = fog iniziale dove XYZ sta per RGB
( con valori fra 0 e 1 per tutte e tre le componenti )
StartFlashScale = scalamento del fog iniziale
TRIGGEREDTEXTURE: il Triggers\TriggeredTexture consente
di effettuare lo switch fra pi∙ texture su una stessa superficie; a tal fine
sulla superficie deve essere posta una ScriptedTexture, il cui aspetto Φ
ininfluente ( contano solo le dimensioni ). Le opzioni sotto
TriggeredTexture>TriggeredTexture:
bTriggerOnceOnly =
pu≥ essere attivato una sola volta
DestinationTexture =
ScriptedTexture su cui effettuare il triggering
Textures = texture da
switchare ( almeno due: la prima Φ quella visualizzata prima del triggering,
dopodichΦ le seguenti vengono sostituite ognuna dopo una attivazione )
Terremoti: sono generati dai KeyPoint\Earthquake. Essi vengono attivati dai Trigger ( evento del Trigger uguale al Tag dell’Earthquake ) e sono impostabili in Earthquake>Earthquake per quanto riguarda magnitudo, durata ed estensione ( in tutte 3 le direzioni dello spazio ), mentre bThrowPlayer indica se il terremoto fa sobbalzare o meno il giocatore. Poi si pu≥ introdurre il rumore del terremoto attraverso un Triggers\SpecialEvent con Tag uguale a quello dell’Earthquake. La scelta del suono Φ in AmbOutside\OneShot ( QuakeXX ); questi suoni tuttavia durano circa 3 secondi, limitando necessariamente la durata del terremoto a tale periodo.
Esplosioni: necessitano di uno o pi∙ Effects\ExplosionChain attivati via Trigger; ricordarsi di spostare gli ExplosionChain dalle pareti in quanto quando li introduciamo essi sono attaccati alla parete e non funzionano. E’ possibile settare tutto il necessario in ExplosionChain>ExplosionChain, mentre per rendere l’effetto pi∙ realistico in presenza di molte esplosioni consiglio di collegare al Trigger anche un Earthquake senza bThrowPlayer. Poi si pu≥ collegare esplosioni ad oggetti quali casse, barili, ecc. In questo modo l'esplosione avviene quando viene distrutto l’oggetto. Conviene cambiare l’ExplosionChain\DelayTime in un valore molto basso ( non per≥ 0 ) per sincronizzare distruzione ed esplosione. Ricordare infine che le esplosioni non possono essere ripetute dopo la prima volta, a differenza dei terremoti.
Innanzitutto conviene distinguere fra musica, suoni d’atmosfera ed effetti sonori: la musica Φ quella che si sente in sottofondo ed Φ attivabile all’inizio del gioco, per poi poter venire cambiata con un MusicEvent. I suoni d’atmosfera vengono eseguiti in loop e sono udibili nella zona in cui si trova l’oggetto che li genera; possono essere introdotti inserendo un SoundFX Looping in >Sound; in alternativa, per facilitα di visione, Φ meglio utilizzare i Keypoint\AmbientSound, che si comportano nella stessa maniera ma hanno una icona specifica. Gli effetti sonori vengono riprodotti una volta sola e necessitano invece di uno SpecialEvent, che va attivato via Trigger.
Per introdurre una musica d’inizio nello schema bisogna andare in Options|Level Properties\Audio\Song e SongSection ( dato che le musiche hanno pi∙ sezioni, di cui dall’editor possiamo ascoltare solo la 0. Per ascoltare le altre, bisogna andare su Windows|Log e digitare da console di comando " musicorder x " , in cui x Φ la SongSection da ascoltare ).
Esportare una musica: innanzitutto andare sotto Music e fare Load del pacchetto da esportare. Tramite l’opzione Export poi si pu≥ effettuare l’esportazione: tuttavia il file ( s3m/xm ) esportato contiene in sequenza tutte le tracce del pacchetto. La riproduzione in WinAmp crea per questo motivo dei problemi: appena la traccia giunge alla fine di una musica non passa alla seguente bens∞ si ferma.
Convertire in wav: anche se questo aspetto non rientra nella trattazione dell'UnrealEd, su richiesta ho deciso di spiegare come passare dalle musiche s3m/xm agli wav. Si pu≥ usare lo stesso WinAmp tramite l’uscita su file: bisogna andare sotto Options|Preferences|Audio I/O e scegliere nella casella Output Plug-Ins il modulo OUT_DISK.DLL ( sotto Configure si pu≥ selezionare la directory di Output ). Se si vuole convertire una musica che non sia la prima del pacchetto, sempre per il problema della riproduzione di WinAmp, bisogna manualmente spostare la barra di scorrimento ( durante la registrazione su wav ) fino al momento di inizio della musica interessata; il risultato non sarα perfetto ( la parte iniziale apparterrα alla prima musica ), ma il problema si risolve lavorando un poco con programmi di editing audio come il Wave Studio. Tutto questo Φ necessario utilizzando WinAmp: se qualcuno conosce un metodo meno doloroso di convertire gli s3m/xm generati dall’UnrealEd in wav, Φ gentilmente invitato a farmelo sapere.
I Mover sono gli unici brush a potersi muovere, traslando o ruotando: essi vengono visualizzati in wireframe anche nelle visuali prospettiche con texture.
In primo luogo create la forma e l’aspetto che volete abbia il Mover attraverso vari poligoni. Fatelo "in aria" in maniera tale da poterlo avvolgere con un brush: dovete infatti introdurre un brush modello pi∙ grande del brush creato e fare Intersect ( se avete fatto tutto giusto ora il brush modello "avvolge" il brush creato, prendendo la stessa forma ). Ora cliccate sull’icona corrispondente ad Add Movable Brush ( dato che il comando da barra degli strumenti non funziona ): questo comando trasforma il brush modello in un Mover. Vedrete un brush di colore viola: questo Φ il Mover, con forma e texture che gli avevate dato, anche se non le potete vedere. Ricordate che non Φ possibile modificare l’aspetto di un Mover: bisogna necessariamente ricreare il modello. Spostate il vecchio brush modello che Φ ancora l∞ e ora fate clic dx sul Mover e scegliete MoverKeyframe\Key1. Questa Φ la seconda posizione che assume il Mover: per il momento ovviamente Φ ancora quella di partenza. Spostate il Mover ( verso l’alto per esempio ) e tornate su MoverKeyframe\Key0. Adesso avete creato due estremi di movimento. Il Mover per≥ si attiva al contatto. Se vogliamo variare l’attivazione dobbiamo usare un Triggers\Trigger e dargli Trigger>Events\Event=Porta ( con Porta il Tag del Mover ). In questa maniera il Trigger agisce sul Mover. Piazziamo il Trigger vicino al Mover, con Collision\CollisionRadius a piacere. Ora scegliamo in Trigger>Trigger\TriggerType la modalitα di attivazione ( preferibilmente TT_PlayerProximity ). Poi posso introdurre in Mover>MoverSounds i suoni pi∙ adatti ( per le porte ad esempio DoorsAnc ), di cui modifico intensitα e raggio in Mover>Sound. Si ricorda che i frames vengono fissati nello spazio in maniera relativa alla posizione di partenza del Mover, non assoluta. Perci≥ Φ possibile per esempio utilizzare lo stesso Mover ( duplicato ) per generare pi∙ porte senza dover reimpostare i frames.
Volendo, per le porte introduciamo un Trigger di fronte ( o in mezzo, se vogliamo l’apertura da entrambi i lati ) con CollisionRadius piuttosto ampio; scegliamo Mover>Object\InitialState=TriggerOpenTimed per farlo aprire e poi chiudersi dal Trigger ( TriggerToggle invece per farlo alternativamente rimanere aperto/chiuso. Per farlo aprire anche sparandogli si deve scegliere Mover>Mover\bDamageTriggered=True ). Selezioniamo un adeguato Mover>Mover\MoveTime e Mover>Mover\StayOpenTime per il movimento e il tempo di attesa. Per esempio un MoveTime=0 pu≥ servire nel caso di un campo di forza che si voglia far sparire sotto controllo di un Trigger: in questo caso basta spostare il Key1 del Mover fuori dalla stanza. Nel caso degli interruttori si pu≥ evitare l’uso dei Trigger utilizzando un interruttore Mover ( che per esempio si preme verso la parete ) che abbia come Event il Tag della porta; selezioniamo per l’interruttore Object\InitialState=BumpButton ( nessuna attesa fra andata e ritorno del Mover ) oppure diamo come Mover\StayOpenTime il tempo che ci vuole perchΘ la porta si richiuda.Per creare Mover con pi∙ frame, bisogna inoltre cambiare Mover>Mover\NumKeys nel numero dei frame ( il predefinito infatti Φ 2 ).
Le opzioni disponibili sotto Mover>Mover:
bDamageTriggered = viene attivato se danneggiato
bDynamicLightMover = l'illuminazione sul Mover
Φ dinamica
BrushRaytraceKey = frame da considerare per il
rendering del Mover ( inutile se bDynamicLightMover=True
)
bTriggerOnceOnly = pu≥
essere attivato una volta sola
BumpEvent = evento da
generare quando qualcuno cade sul Mover
BumpType = tipo di
personaggio che pu≥ cadere sul Mover attivandolo
DamageThreshold =
danno singolo minimo per poter attivare il Mover
qualora bDamageTriggered=True
DelayTime = ritardo
prima del movimento
EncroachDamage = danno
da infliggere a chi tocca il Mover
KeyNum = posizione
attuale
MoverEncroachType =
comportamento del Mover
al contatto con un giocatore
MoverGlideType = modo
di spostarsi ( velocitα costante o con lieve accelerazione )
MoveTime = tempo di
movimento
NumKeys = numero di
frame del movimento
OtherTime =
StayOpenTime quando si Φ in Object\InitialState\TriggerPound
PlayerBumpEvent = evento da generare quando il
giocatore cade sul Mover
ReturnGroup = Tag
del gruppo di ritorno ( altrimenti il Tag
del Mover stesso )
StayOpenTime = ritardo
prima del ritorno
WorldRaytraceKey =
frame da considerare per la generazione delle ombre del Mover
( le ombre non sono dinamiche )
Sotto Mover>MoverSounds:
ClosedSound
= suono OneShot alla fine del ritorno
ClosingSound
= suono OneShot all'inizio del ritorno
MoveAmbientSound
= suono Looping durante il movimento ( sia all'andata che al ritorno )
OpenedSound
= suono OneShot alla fine dell'andata
OpeningSound
= suono OneShot all'inizio dell'andata
I comportamenti possibili in Mover>Object\InitialState:
None = nessuno, ossia continua nella sua condizione senza perturbazioni esterne
( utile per gli oggetti rotanti )
StandOpenTimed = si muove in andata, aspetta lo StayOpenTime
e poi ritorna
BumpButton
= al contatto effettua subito andata e ritorno
BumpOpenTimed
= al contatto si muove in andata, aspetta lo StayOpenTime
e poi ritorna
TriggerPound = ogni volta che si
effettua il ReTrigger del Mover
mentre si sta muovendo, questo ritorna nella posizione di Opened
TriggerControl = il Mover
ritorna solo quando si esce dal raggio del Trigger
usato
TriggerToggle = ogni volta che si effettua
il triggering del Mover,
questo inverte lo stato attuale ( Opened o Closed )
TriggerOpenTimed = effettuato il
triggering si muove in andata, aspetta lo StayOpenTime
e poi ritorna
Illuminazione: per adeguare l’effetto delle luci al Mover in movimento, fare Mover>Mover\bDynamicLightMover=True. Tuttavia l’illuminazione avviene in funzione della posizione del pivot, quindi vi conviene riposizionarlo in maniera tale che l’ombreggiatura vari correttamente; soprattutto il pivot deve trovarsi fuori da altri poligoni, altrimenti il Mover risulterα completamente nero. Un problema nell’operazione di spostamento del pivot si pu≥ avere con Mover complessi, per i quali questa modifica porta ad una confusione nella mappatura delle texture: per ovviarvi bisogna fare in modo che il pivot, quando si crea il Mover, sia giα nella posizione desiderata ( per ottenere questo risultato basta posizionare nel punto desiderato il pivot del brush di avvolgimento del modello: il brush che risulta dall’avvolgimento prende lo stesso pivot). Se invece volete che il Mover abbia sempre l’illuminazione di un suo specifico Keyframe, selezionatelo in Mover\BrushRaytraceKey. Per quanto riguarda invece le ombre create dal Mover, queste non si aggiornano in tempo reale. La cosa migliore in molti casi Φ ignorare la sua ombreggiatura. Si procede cos∞: si utilizza Mover\WorldRaytraceKey che definisce il Keyframe che genera l’ombreggiatura fissa. Se per esempio il nostro Mover ha 4 frames, introduciamo un quinto fuori dallo schema ( dentro ad un muro ) senza per≥ dichiararlo in NumKeys ( che resta 4 ). Ora diamo a WorldRaytraceKey il valore 5 ed avremo ottenuto che il Mover non influenza l’ombreggiatura della stanza a cui appartiene.
AttachMovers: permettono ad un oggetto appoggiato/attaccato al Mover di effettuare i suoi stessi movimenti, siano essi di traslazione che di rotazione. Per fare ci≥ prendete un Brush\Mover\AttachMover e create il vostro Mover con questo ( lo selezionate e fate Add Movable Brush ). Adesso prendete l’oggetto che vi interessa e posizionatelo in funzione del Keyframe0 del Mover. Assicurarsi che l’oggetto abbia Advanced\bStatic=False e Advanced\bMovable=True. Infine in AttachMover>AttachMover\AttachTag il Tag dell’oggetto. Ovviamente se volete utilizzare un maggior numero di oggetti basta dargli lo stesso Tag. Una limitazione viene dal fatto che un attachment non pu≥ seguire un Mover che compie rotazioni su pi∙ di un piano. In alternativa si pu≥ dare all'attachment un Movement\AttachTag uguale al Tag dell'AttachMover.
Create il Mover dell’oggetto che vi interessa far ruotare. Ora fate Mover>Movement\Physics=PHYS_Rotating. Adesso per esempio lo facciamo ruotare sul piano orizzontale: scegliamo in RotationRate la velocitα ( Yaw=5000 per esempio ). Ricordarsi che la rotazione avviene in funzione del pivot del Mover. Volendo possiamo introdurre velocitα per ognuno dei tre tipi, generando evoluzioni complesse, soprattutto spostando il pivot lontano dal Mover. La rotazione Φ fissata, ora facciamo Mover>Mover\MoverEncroachType=ME_IgnoreWhenEncroach. Infine Mover>Object\InitialState=none ( inizia giα in movimento ). Si pu≥ risparmiare la scelta del Physics andando a creare un RotatingMover ( si seleziona Brush\Mover\RotatingMover e poi si effettua il solito Add Movable Brush ). E' possibile far ruotare anche le decorazioni, bisogna solo aggiungere Movement\bFixedRotationDir=True. Per i pickup invece esiste un comando specifico presente in Inventory\bRotatingPickup.
Create il Mover del vetro ( textures in GenIn
): durante questo passaggio mi raccomando, dopo aver creato la
forma ( meglio se attraverso Add Special, two sided e trasparent
) del vetro, non fate subito Add Movable Brush bens∞ avvolgete
il brush attraverso un brush modello pi∙ grande che lo
intersechi: nel caso invece prendiate il brush normale ( che giα
effettivamente occupa lo spazio del vetro appena creato ) non
otterrete la traslucenza. Per creare un vetro consiglio di
utilizzare una sheet con di fronte un poligono invisibile che
simuli la soliditα del vetro: ci≥ Φ preferibile in quanto
intersecare direttamente una superficie trasparente ( come un
vetro poligonale ) con un altro poligono crea fastidiosi effetti
grafici nella zona di intersezione, mentre con le sheet non vi Φ
superficie di intersezione e il problema si evita. Ora
introducete un Effects\ExplodingWall\BreakingGlass e
posizionatelo nel luogo dove volete cadano i frammenti del vetro.
Posizionate il Mover nel Key1 fuori dallo schema, poichΘ
l’esplosione in realtα muove il Mover e genera frammenti,
quindi il Mover alla fine non deve essere visibile. Date
all’Event del Mover il
Tag del BreakingGlass.
Fate ora sul
Mover i seguenti settaggi:
Mover\bDamageTriggered=True
Mover\bTriggerOnceOnly=True ( il vetro altrimenti riappare
)
Mover\MoveTime=0 ( sparisce istantaneamente )
Object\InitialState=TriggerOpenTimed
Sul BreakingGlass invece
fate:
Collision\bProjTarget=False ( altrimenti potete colpire il
BreakingGlass, che Φ invisibile )
ExplodingWall\bTranslucentGlass=True
ExplodingWall\bUnlitGlass=True
ExplodingWall\GlassTexture deve essere uguale alla texture usata per il Mover. Poi in
BreakingGlass>BreakingGlass potete scegliere dimensioni e
quantitα dei frammenti, mentre in Mover>Mover\DamageThreshold la
forza necessaria a distruggere il vetro ( se magari volete che
solo granate o missili siamo efficaci ). Invece per rompere il
vetro al contatto Mover\bDamageTriggered Φ ininfluente e
Object\InitialState=BumpOpenTimed.
Stesso discorso si applica per i muri da distruggere, per i quali per≥ va usato Effects\ExplodingWall e scelta una ExplodingWall\WallTexture adatta.
Come creare un punto da cui si generano oggetti dello stesso tipo.
thingfactory: il
Keypoint\ThingFactory pu≥ generare qualsiasi tipo
di oggetto; le opzioni sono in
ThingFactory>ThingFactory:
bCovert = fa s∞ che gli oggetti
appaiano solo se il giocatore non pu≥ vederli apparire
bFalling = vero se l'oggetto non Φ di classe
Pawn
bOnlyPlayerTouched =
si attiva solo a contatto col giocatore ( impostare un adeguato Collision\CollisionRadius
)
bStoppable = si pu≥
fermare se si esce dal suo raggio d'azione
capacity
= quantitα di oggetti da far apparire ( -1 per capacitα illimitata )
interval = frequenza di apparizione, capacitα
prototype = definisce
l’oggetto da riprodurre
maxitems
= numero massimo di oggetti presenti contemporaneamente
timeDistribution = distribuzione degli oggetti nel tempo
Ora bisogna introdurre il punto in cui appariranno: NavigationPoint\Spawnpoint,
a cui basta solo dare lo stesso Tag del ThingFactory.
arrowspawner: l'Effects\ArrowSpawner
lancia frecce con traiettoria rettilinea. Per
definire la direzione di default delle frecce ( analogamente poi per
BoulderSpawner
e
MortarSpawner
) Φ necessario orientare in
tutte e tre le dimensioni la freccia rossa che parte dall' ArrowSpawner
( visibile nelle visuali planari ). Questo oggetto
va attivato via Trigger
per poter operare. Le opzioni in
ArrowSpawner>ArrowSpawner:
ArrowSpeed
= velocitα delle frecce
ArrowsToShootAfterDeactivated
= frecce aggiuntive da lanciare dopo la disattivazione
RepeatDelay
= tempo di attesa per la riattivazione
TriggerDelay
= ritardo rispetto all'attivazione da parte del Trigger
boulderspawner: l'Effects\BoulderSpawner lancia una pietra frammentaria. L'unica opzione funzionante Φ BoulderSpawner\BoulderSpeed per definire la velocitα. Questo oggetto va attivato via Trigger per poter operare.
mortarspawner: l'Effects\MortarSpawner
lancia colpi di mortaio, e le sue
impostazioni sono in MortarSpawner>MortarSpawner:
bDeviate
= consente di stabilire un margine di errore per la direzione di lancio del
mortaio
Deviation
= fattore di errore ( inteso in tutte le dimensioni ) del lancio del mortaio
RateOfFire
= frequenza di tiro
ShellBlastRadius
= raggio di deflagrazione del proiettile
ShellDamage
= danno inferto dal proiettile
ShellSpeed
= velocitα del proiettile
PATHPOINT: se volete che un oggetto compia una sola volta
un tragitto complesso, potete usare i Keypoint\PathPoint. Essi
permettono al Mover di compiere spostamenti in tutte tre le
direzioni dello spazio. Innanzitutto create il Mover
dell’oggetto da spostare, dategli un Tag definito ( es.
PathMover ) e fate:
Mover\bDynamicLightMover=True
Mover\MoverEncroachType=ME_IgnoreWhenEncroach
Object\InitialState=None
Ora introducete un Keypoint\ObjectPath
e dategli un determinato Tag ( es. Path ). In
ObjectPath\ObjectPath scegliete se durante il movimento Pitch,
Roll e Yaw restano inalterati, oppure se seguono il movimento.
Invece in PathActorTag inserite il Tag del Mover. Ora introducete
tutti i nodi del sentiero che volete creare attraverso PathPoint.
Date ad ogni PathPoint lo stesso Tag dell’ObjectPath e in
PathPoint>PathPoint ordinate i sequence_Number nell’ordine
che vi interessa. In curveSpeed e speedU si definiscono velocitα
di rotazione e di spostamento nel tragitto verso il PathPoint
attuale ( non quello successivo ). Il primo e l’ultimo
PathPoint non contano nel tragitto ( si parte dal secondo ),
servono solo a definire la rotazione di partenza e quella di
arrivo. Il Mover poi pu≥ essere posizionato in qualsiasi punto,
come del resto l’ObjectPath: durante il gioco vedrete il
Mover posto col pivot corrispondente alla posizione del secondo
PathPoint.
INTERPOLATIONPOint: qualora
invece si voglia far percorrere al giocatore un tragitto liberamente nello
spazio, bisogna usare i Keypoint\InterpolationPoint.
Il sistema parte da un Trigger
che, azionato dal giocatore, viene collegato ad uno SpecialEvent;
bisogna fare SpecialEvent>Object\InitialState=PlayerPath,
dopodichΦ si inizia ad introdurre gli InterpolationPoint, che definiscono i
cambiamenti di traiettoria del percorso, perci≥ bisogna usarne uno per ogni
nodo del tragitto. I Tag
degli InterpolationPoint
devono essere uguali all'Event
dello SpecialEvent.
Sotto InterpolationPoint>InterpolationPoint
vi sono alcune opzioni, le uniche necessarie sono:
bEndOfPath = vero se
Φ l'ultimo nodo del tragitto
Position = numero
d'ordine del nodo ( il primo Φ 0 )
RateModifier =
variazione di velocitα nel passaggio al seguente nodo ( 1 di default )
Inoltre bisogna orientare la freccia che parte dall'InterpolationPoint
di modo che punti verso il nodo seguente.
Tutti gli oggetti presenti in questo capitolo si trovano sotto NavigationPoint e consentono una migliore interpretazione da parte dei bot della geometria e dell'oggettistica del livello in modo da utilizzare tutte le risorse disponibili.
PlayerStart: con i PlayerStart Φ possibile introdurre punti di respawn dei giocatori, umani o bot che siano. L'implementazione Φ semplice: l'unico settaggio da fare Φ correggere la direzione di respawn ruotando ( CTRL+click destro ) la freccia rossa che proviene dal PlayerStart. La quantitα di PlayerStart da inserire Φ dipendente dalle dimensioni del livello, mentre Φ consigliabile posizionarli nei luoghi meno frequentati e pi∙ difficili da raggiungere, in modo da fornire protezione dagli attacchi in partenza e distribuire meglio i bot all'interno del livello.
PathNode: anzitutto l'AI dei bot necessita della presenza all'interno di un livello dei PathNode, che vanno inseriti possibilmente in presenza di percorsi non intuitivi e per suggerire ai bot delle traiettorie migliori o dei punti altrimenti poco frequentati. In generale per il posizionamento dei PathNode bisogna seguire le traiettorie usuali con cui si raggiungono i punti principali del livello ( esclusi i salti, per i quali si utilizzano classi pi∙ specifiche ). Ogni PathNode dovrebbe risultare visibile da quello precedente, ad una distanza minore di 700 unitα in orizzontale e 350 in verticale, mentre la distanza minima Φ 50 unitα. Gli oggetti dell'inventario ( munizioni, bonus e armi ) sono considerati giα di classe NavigationPoint e non Φ necessario posizionare PathNode nelle immediate vicinanze.
Alla fine della creazione dei tragitti per il livello, bisogna fare un Paths Define ( il bottone Φ presente sotto Lighting Rebuilt ): questo procedimento imposta i collegamenti fra tutti i NavigationPoint e genera linee che collegano questi ultimi: per vederle bisogna scegliere nelle opzioni dei quadranti, sotto View, la modalitα Show Paths; compariranno diversi segmenti di colori blu e rossi: quelli rossi sono da ritenersi peggiori ( il tragitto Φ meno pulito, con pi∙ ostacoli ) e quindi da modificare preferibilmente. Ogni volta che si effettua una modifica alla geometria ( oppure si introduce una nuova classe di tipo NavigationPoint ) Φ necessario effettuare il Rebuilt dei Paths.
blockedpath: rende un tragitto non percorribile fino a che un Trigger non disabilita il BlockedPath stesso; l'uso primario Φ nei casi in cui un tragitto non possa essere completato a causa di un ostacolo rimuovibile ( come capita spesso in partite di Assault ). Una volta sbloccato il tragitto, non Φ pi∙ possibile bloccarlo nuovamente.
LiftExit e LiftCenter: queste classi sono adibite usualmente all'utilizzo di ascensori/piattaforme. Il LiftCenter va posizionato sopra il Mover della piattaforma ( o comunque con posizione XY analoga ), mentre i due LiftExit devono essere alle due estremitα del movimento della piattaforma. PerchΦ il sistema funzioni, il LiftCenter>LiftCenter\LiftTag e i LiftExit>LiftExit\LiftTag devono essere uguali. Inoltre Φ consigliabile che il Mover della piattaforma abbia Object\InitialState=StandOpenTimed piuttosto che BumpOpenTimed, in quanto quest'ultima modalitα crea problemi di comportamento dei bot. Inoltre Φ possibile utilizzare questo metodo per suggerire cadute o spostamenti che non comportino salti da parte del bot ( altrimenti si utilizza il JumpSpot ), oppure per esempio per far raggiungere al bot un certo punto ( magari con un bonus interessante ) e farlo subito ritornare indietro perchΦ ci sono delle trappole in prossimitα del bonus.
JumpSpot,
TRANSLOCdest e translocstart: per consentire ai bot di saltare o usare
il translocator bisogna introdurre un LiftCenter\JumpSpot ( che funge da
LiftCenter ) ed i relativi LiftExit. Il JumpSpot
va posizionato nel punto da raggiungere col salto, un LiftExit in
prossimitα del JumpSpot ( per scendere eventualmente dall'altura
) e l'altro a terra, dove si ritiene pi∙ adatto spiccare il
salto. L'associazione va effettuata ponendo uguali i
LiftExit>LiftExit\LiftTag e il JumpSpot>LiftCenter\LiftTag.
Per il LiftExit di partenza Φ possibile impostare sotto
LiftExit\LiftTrigger il Tag di un Trigger che determini la
possibilitα di fare il salto ( per esempio, Φ meglio impedire
il salto se la destinazione Φ al momento irraggiungibile; quando
essa diverrα agibile, si farα in modo che quest'ultimo evento
attivi il LiftExit ). Se si deve imporre uno spostamento
attraverso translocator, si usa un LiftCenter\Translocdest
al
posto del LiftCenter ed un LiftExit\TranslocStart al posto del
LiftExit di partenza, dopodichΦ si impostano LiftTag uguali. Altre opzioni sotto JumpSpot>JumpSpot:
bAlwaysAccel = consiglia al
bot di giungere al JumpSpot
anche per via aerea ( da usarsi soprattutto se i bot non tendono ad usare
quest'oggetto )
bImpactJump
= consente al bot di raggiungere il punto tramite un ImpactJump ( con l'Impact
Hammer )
AmbushPoint e
DefensePoint: l'AmbushPoint
agisce
indipendentemente ed Φ utile per scegliere punti idonei al cecchinaggio. Le impostazioni sotto AmbushPoint>AmbushPoint
sono bSniping per consentire il cecchinaggio e SightRadius,
impostato ad un valore estremamente alto. Invece il AmbushPoint\DefensePoint serve in partite a squadre per
fornire punti preferenziali di difesa: in questo caso va
selezionato sotto DefensePoint>DefensePoint:
Team = squadra di appartenenza ( 0=Rosso, 1=Blu, 2=Verde, 3=Oro
)
Priority = da 1 in su, per decidere per ordine di
disponibilitα il DefensePoint da occupare
FortTag = serve in
Assault ad
associare il punto ad uno specifico FortStandard,
in modo da fornire un punto di difesa preferenziale per quella zona
In questo capitolo verranno analizzati i principali oggetti da introdurre nelle varie modalitα:
teamcannon: un
Pawn\StationaryPawn\TeamCannon
( oppure Pawn\StationaryPawn\TeamCannon\MinigunCannon
) attacca tutti i giocatori non appartenenti alla sua squadra; di conseguenza
pu≥ essere usato in qualsiasi partita CTF, AS, DOM e TeamMatch, mentre in
normale DeathMatch/Last Man Standing la torretta colpisce chiunque. Settaggi
utili:
TeamCannon\MyTeam
= definisce la squadra di appartenenza
TeamCannon\FireSound
= suono associato allo sparo
TeamCannon\ProjectileType
= tipo di proiettile ( per sostituirlo scegliere un esponente di classe
Projectile, tenendo per≥ conto che la frequenza di sparo Φ fissata )
Pawn\Health
= vita della torretta; una volta esaurita, la torretta rimane in idle senza
attaccare
DOMINATION
CONTROLpoint: unica
classe veramente necessaria Φ il NavigationPoint\ControlPoint,
in un numero variabile generalmente fra 2 e 4, facendo attenzione a non
posizionarli troppo vicini ad un'altra classe di tipo NavigationPoint. Le
opzioni disponibili sotto ControlPoint>ControlPoint:
BlueEvent
= evento associato al possesso del punto di controllo da parte della squadra blu
( in generale non necessario )
GoldEvent
= evento associato al possesso da parte
della squadra oro
GreenEvent
= evento associato al possesso da parte della squadra verde
RedEvent
= evento associato al possesso da parte della squadra rossa
bSelfDisplayed
= visibilitα dell'oggetto ( normalmente visibile )
ControlSound
= suono associato al possesso del punto di controllo
PointName
= nome del punto di controllo
CAPTURE THE FLAG
FLAGBASE: questa classe ( NavigationPoint\FlagBase ) non Φ altro che la bandiera della squadra; l'implementazione Φ molto semplice, in quanto per ognuna delle due squadre bisogna assegnare il corretto FlagBase\Team.
alternatepath: consente di dare ad un componente di squadra una gamma di alternative di percorsi a lunga distanza per raggiungere la FlagBase nemica. Il NavigationPoint\AlternatePath sotto AlternatePath\Team imposta la squadra a cui si riferisce ( 1 Blu, 0 Rosso ) mentre in SelectionWeight si sceglie il "peso" che il bot deve dare alla destinazione in questione. Il bot sceglierα la destinazione pi∙ idonea alla sua posizione, preferendo se possibile quella con maggiore peso; pi∙ alta Φ la differenza di peso, pi∙ probabile Φ la scelta fissa di un tragitto ( pu≥ essere utile se si vuole percorrere la strada alternativa solo quando gli si Φ molto vicini ). Naturalmente maggiore quantitα di AlternatePath si inserisce, pi∙ precisa Φ l'analisi del migliore tragitto da parte del bot. Comunque non vanno confusi con i PathNode: gli AlternatePath vanno distribuiti lontani fra loro ( non in prossimitα dei bivi che generano le strade alternative, insomma ) per non creare confusione nel bot ed Φ inutile usare pi∙ AlternatePath del numero di bivi a disposizione.
ASSAULT
FORTSTANDARD: il
Pawn\StationaryPawn\FortStandard definisce
un punto da difendere nella logica della mappa di Assault interessata: in teoria
ogni punto critico andrebbe dotato di FortStandard,
per≥ per aumentare l'efficacia della difesa si possono definire svariati punti
da difendere. Le opzioni in
FortStandard>FortStandard:
bFinalFort
= vero solo per il punto che, se raggiunto dagli attaccanti, termina il livello
bFlashing =
se l'oggetto lampeggia quando colpito
bForceRadius
= consente di definire il raggio all'interno del quale i bot devono attaccare il
FortStandard
( scegliere ChargeDist
adeguato )
bSayDestroyed = avverte dell'espugnazione
del punto ( da disattivare se il punto non Φ associato ad un oggetto fisico
oppure se Φ un FinalFort )
bSelfDisplayed
= se il mesh del FortStandard
Φ visibile ( normalmente no, in caso contrario si scelga anche una corretta Pawn\Visibility
)
bTriggerOnly = se il punto pu≥ essere
espugnato solo a contatto o tramite Trigger
( altrimenti bisogna distruggerlo,
impostando Pawn\Health adeguata
)
ChargeDist
= distanza massima perchΦ i bot valutino
di attaccare il FortStandard
DamageEvent
= consente di attivare una serie di eventi una volta danneggiato di un certo
fattore il FortStandard
DamageEventThreshold =
quantitα di danno per colpo singolo da infliggere per attivare l'evento
corrispondente ( serve affinchΦ un certo evento sia attivabile colpendo solo
tramite armi potenti )
DefensePriority
= prioritα di difesa rispetto agli altri FortStandard
( 0 per il FinalFort, crescente quanto pi∙ ci si allontani da lui )
DefenseTime
= durata della difesa ( tempo massimo per gli attaccanti affinchΦ espugnino il
FinalFort ); per praticitα va impostato solo al FinalFort
DestroyedMessage
= messaggio seguente la distruzione ( il messaggio verrα preceduto dal FortName
)
EndCamTag
= Tag
della SpectatorCam
con cui si apre la sequenza di vittoria degli attaccanti ( solo per il FinalFort
)
FallBackFort
= Tag
del FortStandard
da presidiare in ritirata una volta che gli attaccanti hanno espugnato
questo
FortName =
nome del punto da difendere
NearestPathNodeTag
= Tag
del PathNode
pi∙ vicino ( serve a facilitare il raggiungimento del punto da parte dei bot ):
necessita appunto dell'assegnazione di un Tag
univoco al pi∙ vicino PathPoint
ASSAULTinfo: in
ogni livello Assault Φ necessario un Info\AssaultInfo:
tramite questo si possono definire gli obiettivi e gli screenshots associati. Le
opzioni sono sotto AssaultInfo>AssaultInfo:
NumObjShots
= numero di obiettivi ( normalmente uno per FortStandard,
ma non necessariamente qualora alcuni di questi ultimi fungano solo da
segnalazione dell'arrivo di attaccanti )
ObjDesc
= descrizione dei singoli obiettivi ( l'ultimo Φ quello relativo al FinalFort )
ObjShots
= screenshots dei singoli obiettivi ( importare immagini 256x256 nel pacchetto MyLevel e
poi utilizzarle; non Φ necessario salvare il pacchetto, in quanto viene
integrato nel file di livello )
spectatorcam: qualora
gli attaccanti riescano a vincere la partita, la visuale passa per tutti i
giocatori ad una Keypoint\SpectatorCam,
la quale illustra la scena finale da un certo punto di vista. Notare che la SpectatorCam
non risulta normalmente visibile: per vederla bisogna scegliere nelle barre dei
quadranti Actors|Icon View ( comparirα un occhio ). A questo punto si pu≥
modificare la posizione e la direzione di questa telecamera. Infine sotto SpectatorCam\FadeOutTime
si sceglie la durata della telecamera.
Per creare una scena finale conviene introdurre un teamtrigger
in prossimitα del FinalFort:
il teamtrigger
si attiva solo in presenza di giocatori non appartenenti alla squadra definita
dal teamtrigger>teamtrigger\Team,
quindi solo quando il FinalFort viene espugnato. Perci≥ la SpectatorCam
viene attivata pi∙ o meno in contemporanea col teamtrigger,
al quale possiamo collegare per esempio un Dispatcher
per eseguire esplosioni, suoni, ecc.
ASSAULTRANDOMIZER: il NavigationPoint\AssaultRandomizer permette di variare i tragitti di attacco tecnicamente facendo credere ai bot che un tragitto sia pi∙ lungo di un altro ( loro scelgono sempre quello con minore Cost, ossia tempo di percorrenza ): a questo fine bisogna posizionare l'AssaultRandomizer in un punto chiaro del tragitto pi∙ breve impostando un AssaultRandomizer\ToggledCost tale per cui questo tragitto risulti pi∙ lungo dell'altro ( bisogna andare a tentativi oppure dargli un valore molto alto ), poi gli si collega un Trigger posizionandolo preferibilmente un po' prima del bivio per i due tragitti: il risultato Φ che ogni volta che lo si attiva il Trigger cambia, tramite l'AssaultRandomizer, il tragitto con minore Cost.